#include "view.h"
#include "display_ctrl.h"
#include "view_abstract.h"
#include "platform_assert.h"
#include "app_trace.h"
#include "prompt/view_prompt.h"
#include "system/view_system.h"
#include "prj_typedef.h"
#include "times/view_times.h"
#if defined(NO_DETAILS)
#else
#include "details/view_details.h"
#endif
#include "heart_rate/view_heart_rate.h"
#include "sports/view_sports.h"
#include "relax/view_relax.h"
#include "metronome/view_metronome.h"
#include "messages/view_messages.h"
#include "others/view_others.h"
#include "weather/view_weather.h"
#include "sports_mode.h"
#include "motor.h"
#include "blecom.h"
#if defined(USE_CT1711)
#include "temperature/temperature.h"
#endif
#ifdef UI_BLOOD_PRESSURE
#include "blood_pressure/blood_pressure.h"
#endif
#ifdef UI_BLOOD_OXYGEN
#include "blood_oxygen/blood_oxygen.h"
#endif
#ifdef USE_CT1711
#include "body_temperature.h"
#endif
#if defined(W01_PROJECT)
#include "view_device_reset.h"
#endif
#if defined(DISTANCE_ESTIMATE)
#include "distance_estimate/view_distance_estimate.h"
#endif
#ifdef MUSIC_UI
#include "music/view_music.h"
#endif
#if defined(UI_STEPS)
#include "steps/view_steps.h"
#endif
#if defined(UI_CALORIES)
#include "calories/view_calories.h"
#endif
#ifdef UI_CHOLESTREROL
#include "view_cholestrerol/view_cholestrerol.h"
#endif
#ifdef UI_BLOOD_GLUCOSE
#include "view_blood_glucose/view_blood_glucose.h"
#endif
#include "m_product_test.h"
#define LOG(fmt, ...) app_trace_log(fmt "\r\n", ##__VA_ARGS__)
PLATFORM_STATIC_ASSERT(view_normal_start < VIEW_LEVEL_0_SUB_COUNT, "error");
typedef struct __view_level_0_t
{
    abstract_view_display display;
    abstract_view_event event;
} view_level_0_t;

view_level_0_t const view_level_0_interface[] = {
    {view_time_display, view_time_event},
#ifdef UI_BLOOD_OXYGEN
    {view_blood_oxygen_display, view_blood_oxygen_event},
#endif
#if defined(USE_CT1711)
    {view_temperature_display, view_temperature_event},
#endif
    {view_heart_rate_display, view_heart_rate_event},
#if defined(NO_DETAILS)
#else
    {view_details_display, view_details_event},
#endif
    {view_sports_display, view_sports_event},

#ifdef NO_WEATHER_UI
#else
    {view_weather_display, view_weather_event},
#endif

#ifdef NO_RELAX_UI
#else
    {view_relax_display, view_relax_event},
#endif
#ifdef NO_METRONOME_UI
#else
    {view_metronome_display, view_metronome_event},
#endif
#ifdef NO_MESSAGE_LEVLE_0_UI
#else
    {view_message_display, view_message_event},
#endif
    {view_others_display, view_others_event},
};



view_level_0_t const *get_level_0_interface(int32_t view)
{
    if (view < view_start || view >= view_end)
    {
        return 0;
    }
    int view_index = (view - view_start) / VIEW_LEVEL_0_SUB_COUNT;
    if (view_index >= sizeof(view_level_0_interface) / sizeof(view_level_0_interface[0]))
    {
        Ensures(0);
        return 0;
    }
    return &view_level_0_interface[view_index];
}

/**
 * @brief
 *
 * @param view
 * @param level_index 当前级数的第几个页面
 * @return view_level_t 几级页面
 */
view_level_t get_view_level(int32_t view, int *p_level_index)
{
    int remainder = view - view_start; //!< 余数
    int quotient = 0;                  //!< 商
    quotient = remainder / VIEW_LEVEL_0_SUB_COUNT;
    remainder = remainder % VIEW_LEVEL_0_SUB_COUNT;
    if (remainder == 0)
    {
        if (p_level_index != 0)
        {
            *p_level_index = quotient;
        }
        return view_level_0;
    }
    quotient = remainder / VIEW_LEVEL_1_SUB_COUNT;
    remainder = remainder % VIEW_LEVEL_1_SUB_COUNT;
    if (remainder == 0)
    {
        if (p_level_index != 0)
        {
            *p_level_index = quotient;
        }
        return view_level_1;
    }
    quotient = remainder / VIEW_LEVEL_2_SUB_COUNT;
    remainder = remainder % VIEW_LEVEL_2_SUB_COUNT;
    if (p_level_index != 0)
    {
        *p_level_index = quotient;
    }
    //!< 三级页面
    return view_level_2;
}
/**
 * @brief 同级切换,上一个页面
 *
 * @param view
 */
void level_0_move_previous_view(int32_t view)
{
    int level_index = 0;
    view_level_t view_level = get_view_level(view, &level_index);
    int32_t new_view = 0;
    disp_mode_t disp_mode = DISP_MODE_NORMAL;
    if (level_index == 1 && view_level != view_level_0)
    {
        return;
    }
    if (level_index == 0 && view_level == view_level_0)
    {
        new_view = view_end - VIEW_LEVEL_0_SUB_COUNT;
        disp_mode = DISP_MODE_UP_MOVE;
    }
    else
    {
        switch (view_level)
        {
        case view_level_0:
            // return ;
            disp_mode = DISP_MODE_UP_MOVE;
            new_view = view - VIEW_LEVEL_0_SUB_COUNT;
            break;
        case view_level_1:
            disp_mode = DISP_MODE_UP_MOVE;
            new_view = view - VIEW_LEVEL_1_SUB_COUNT;
            break;
        case view_level_2:
            disp_mode = DISP_MODE_UP_MOVE;
            new_view = view - VIEW_LEVEL_2_SUB_COUNT;
            break;
        }
    }
    LOG("view[%d] level[%d] previous view[%d] ", view, view_level, new_view);
    display_show(new_view, disp_mode);
}

/**
 * @brief 同级切换，下一个页面
 *
 * @param view
 */
void level_0_move_next_view(int32_t view)
{
    int level_index = 0;
    view_level_t view_level = get_view_level(view, &level_index);
    int32_t new_view = 0;
    disp_mode_t disp_mode = DISP_MODE_NORMAL;
    view_level_t new_view_level = view_level_0;
    switch (view_level)
    {
    case view_level_0:
        disp_mode = DISP_MODE_DOWN_MOVE;
        new_view = view + VIEW_LEVEL_0_SUB_COUNT;
#if 0
#warning debug
        if (new_view == view_relax)
        {
            new_view = view_messages;
        }
#endif
        if (new_view == view_end)
        {
            new_view = view_start;
        }
        break;
    case view_level_1:
        disp_mode = DISP_MODE_DOWN_MOVE;
        new_view = view + VIEW_LEVEL_1_SUB_COUNT;
        new_view_level = get_view_level(new_view, 0);
        if (new_view_level != view_level)
        {
            return;
        }
        break;
    case view_level_2:
        disp_mode = DISP_MODE_DOWN_MOVE;
        new_view = view + VIEW_LEVEL_2_SUB_COUNT;
        new_view_level = get_view_level(new_view, 0);
        if (new_view_level != view_level)
        {
            return;
        }
        break;
    }
    LOG("view[%d] level[%d] next_view view[%d] ", view, view_level, new_view);
    display_show(new_view, disp_mode);
}
/**
 * @brief 右边的下一页
 *
 * @param view
 */
void level_0_level_down(int32_t view)
{
    view_level_t view_level = get_view_level(view, 0);
    int32_t new_view = 0;
    switch (view_level)
    {
    case view_level_0:
        // #warning debug
        //         return;
        new_view = view + VIEW_LEVEL_1_SUB_COUNT;
        break;
    case view_level_1:
        new_view = view + VIEW_LEVEL_2_SUB_COUNT;
        break;
    case view_level_2:
        return;
    }
    LOG("view[%d] level[%d] entry view[%d] ", view, view_level, new_view);
    display_show(new_view, DISP_MODE_NORMAL);
}
/**
 * @brief 1级页面回首页，其他页面回一级页面
 *
 * @param view
 */
void level_0_level_up(int32_t view)
{
    int level_index = 0;
    view_level_t view_level = get_view_level(view, &level_index);
    int32_t new_view = 0;

    switch (view_level)
    {
    case view_level_0:
        // new_view = view - level_index * VIEW_LEVEL_0_SUB_COUNT;
        new_view = view_time;
        break;
    case view_level_1:
        new_view = view - level_index * VIEW_LEVEL_1_SUB_COUNT;
        break;
    case view_level_2:
        new_view = view - level_index * VIEW_LEVEL_2_SUB_COUNT;
        break;
    }
    LOG("view[%d] level[%d] back view[%d] ", view, view_level, new_view);
    display_show(new_view, DISP_MODE_NORMAL);
}
#ifdef EVENT_PREVIOUS_VIEW
void event_previous_view_broadcast(void)
{
    event_param_t param = {
        .source = event_source_system,
        .event = event_move_previous_view,
    };
    view_event(param);
}
#endif
#ifdef EVENT_NEXT_VIEW
void event_next_view_broadcast(void)
{
    event_param_t param = {
        .source = event_source_system,
        .event = event_move_next_view,
    };
    view_event(param);
}
#endif
#ifdef EVENT_LEVEL_UP
void event_level_up_broadcast(void)
{
    event_param_t param = {
        .source = event_source_system,
        .event = event_move_level_up,
    };
    view_event(param);
}
#endif //!<#ifdef EVENT_LEVEL_UP
#ifdef EVENT_LEVEL_DOWN
void event_level_down_broadcast(void)
{
    event_param_t param = {
        .source = event_source_system,
        .event = event_move_level_down,
    };
    view_event(param);
}
#endif
#ifdef EVENT_BUTTON_FRONT
void event_button_front_press_broadcast(void)
{
    event_param_t param = {
        .source = event_source_system,
        .event = event_button_front_press,
    };
    view_event(param);
}

void event_button_front_long_press_broadcast(void)
{
    event_param_t param = {
        .source = event_source_system,
        .event = event_button_front_long_press,
    };
    view_event(param);
}
#endif
void event_transition(event_param_t param)
{
    switch (param.source)
    {
#ifdef EVENT_BUTTON_FRONT
    case event_source_button_front:
    {
        switch (param.event)
        {
        case BUTTON_EVENT_SHORT_PRESS:
            event_button_front_press_broadcast();
            break;
        case BUTTON_EVENT_LONG_PRESS:
            event_button_front_long_press_broadcast();
            break;
        }
        break;
    }
#endif
#ifdef EVENT_BUTTON_SIDE
    case event_source_button_side:
    {
        switch (param.event)
        {
        case BUTTON_EVENT_SHORT_PRESS:
            if (display_get_present_type() != view_time || disp_ctrl.on == DISP_ON_DISABLE)
            {
                display_show(view_time, DISP_MODE_NORMAL);
            }
            else
            {
                disp_ctrl.auto_close_delay = 1;
            }
            break;
#ifdef POWER_OFF_MS
        case BUTTON_EVENT_LONG_PRESS_KEEP:
        {
            if (DeviceState.PowerState == POWEROFFOK)
            {
                view_power_on_event(param);
            }
            else
            {
                product_test_state_t state = product_test_state_get();
                switch (state)
                {
                case PRODUCT_TEST_STATE_TEST_NONE:
                    break;
                case PRODUCT_TEST_STATE_TEST_PCBA:
                    break;
                case PRODUCT_TEST_STATE_TEST_ASSEM:
                    if (param.long_press_millisecond >= POWER_OFF_MS)
                    {
                        motor_start(500);
                        system_into_poweroff();
                    }
                    break;
                }
                break;
            }
        }
        break;
#else
        case BUTTON_EVENT_LONG_PRESS:
            if (DeviceState.PowerState == POWEROFFOK)
            {
                view_power_on_event(param);
            }
            else
            {
                product_test_state_t state = product_test_state_get();
                switch (state)
                {
                case PRODUCT_TEST_STATE_TEST_NONE:
                    break;
                case PRODUCT_TEST_STATE_TEST_PCBA:
                    break;
                case PRODUCT_TEST_STATE_TEST_ASSEM:
                    motor_start(500);
                    system_into_poweroff();
                    break;
                }
                break;
            }
            break;
#endif
        }
    }
#endif
#ifdef USE_TOUCHPAD
    case event_source_touch:
    {
        switch (param.event)
        {
        case BUTTON_EVENT_TP_MOVE_UP:
            event_previous_view_broadcast();
            break;
        case BUTTON_EVENT_TP_MOVE_DOWN:
            event_next_view_broadcast();
            break;
        case BUTTON_EVENT_TP_TAP:
        case BUTTON_EVENT_TP_MOVE_LEFT:
            event_level_down_broadcast();
            break;
        case BUTTON_EVENT_TP_MOVE_RIGHT:
            event_level_up_broadcast();
            break;
        }
    }
#endif
    }
}

bool level_0_event_handle(int32_t view, event_param_t param)
{
    if (view < view_start || view >= view_end)
    {
        return false;
    }
    view_level_0_t const *level_0 = get_level_0_interface(view);
    if (level_0 == 0)
    {
        return false;
    }
    view_event_result_t result = level_0->event(view, &param);
    if (result == view_event_result_handled)
    {
        return true;
    }
    if (param.source == event_source_system)
    {
        switch (param.event)
        {
#ifdef EVENT_PREVIOUS_VIEW
        case event_move_previous_view:
            level_0_move_previous_view(view);
            return true;
#endif //!<#ifdef EVENT_PREVIOUS_VIEW
#ifdef EVENT_NEXT_VIEW
        case event_move_next_view:
            level_0_move_next_view(view);
            return true;
#endif
#ifdef EVENT_LEVEL_UP
        case event_move_level_up:
            level_0_level_up(view);
            return true;
#endif //!< #ifdef EVENT_LEVEL_UP
#ifdef EVENT_LEVEL_DOWN
        case event_move_level_down:
            level_0_level_down(view);
            return true;
#endif
#ifdef EVENT_BUTTON_FRONT
        case event_button_front_press:
            level_0_move_next_view(view);
            return true;
        case event_button_front_long_press:
            level_0_level_down(view);
            return true;
#endif
        default:
            return false;
        }
    }
    return false;
}
void view_event(event_param_t param)
{
    int32_t view = view_prompt_camera_ready;
    if (DeviceState.PowerState == POWEROFFOK && param.event != event_view_exit)
    {
        view_power_on_event(param);
        view_power_off_charing_event(param);
        return;
    }
    if (disp_ctrl.on == DISP_ON_DISABLE)
    {
        switch (param.event)
        {
        case BUTTON_EVENT_SHORT_PRESS:
        case BUTTON_EVENT_LONG_PRESS:
        case BUTTON_EVENT_LONG_PRESS_KEEP:
#ifdef USE_TOUCHPAD
        case BUTTON_EVENT_TP_TAP:
        case BUTTON_EVENT_TP_TAP_LONG:
        case BUTTON_EVENT_TP_MOVE_UP:
        case BUTTON_EVENT_TP_MOVE_DOWN:
        case BUTTON_EVENT_TP_MOVE_LEFT:
        case BUTTON_EVENT_TP_MOVE_RIGHT:
#endif
            //!< 已灭屏，要把屏点亮
            LOG("put screen power on");
#ifdef IT_POWER_01_UI
            if (view == view_close_oled || view == view_empty)
            {
                // start_body_measure(0, false, view_time);
                start_rise_wrist_measure(view_time);
            }
            else
            {
                disp_type_priority_t prio = display_get_present_type_priority();
                if (prio < DISP_TYPE_PRIORITY_APP_MEASURE)
                {
                    // start_body_measure(0, false, view);
                    start_rise_wrist_measure(view);
                }
                else
                {
                    display_show(view, DISP_MODE_NORMAL);
                }
            }
#else
            if (view == view_close_oled)
            {
                view = view_empty;
            }
            display_show(view, DISP_MODE_NORMAL);
#endif
            return;
        }
    }
    switch (param.event)
    {
    case BUTTON_EVENT_SHORT_PRESS:
    case BUTTON_EVENT_LONG_PRESS:
    case BUTTON_EVENT_LONG_PRESS_KEEP:
#ifdef USE_TOUCHPAD
    case BUTTON_EVENT_TP_TAP:
    case BUTTON_EVENT_TP_TAP_LONG:
    case BUTTON_EVENT_TP_MOVE_UP:
    case BUTTON_EVENT_TP_MOVE_DOWN:
    case BUTTON_EVENT_TP_MOVE_LEFT:
    case BUTTON_EVENT_TP_MOVE_RIGHT:
#endif
        if (disp_ctrl.auto_close_delay < DISP_CLOSE_TIME_DEFAULT)
        {
            disp_ctrl.auto_close_delay = DISP_CLOSE_TIME_DEFAULT;
        }
        break;
    }
    if (finished_product_event(view, param) == view_event_result_handled)
    {
        return;
    }
    if (level_0_event_handle(view, param))
    {
        return;
    }
    if (view_prompt_event(view, param))
    {
        return;
    }
    if (view_system_event(view, param))
    {
        return;
    }
    event_transition(param);
}
void view_display(void)
{
    int32_t view =view_prompt_camera_ready;
    if (finished_product_display(view))
    {
        return;
    }
    view_level_0_t const *level_0 = get_level_0_interface(view);
    if (level_0 != 0)
    {
        level_0->display(view);
        return;
    }
    if (view_prompt_display(view))
    {
        return;
    }
    if (view_system_display(view))
    {
        return;
    }
}
bool is_view_exit_to_empty(int view)
{
    switch (disp_ctrl.current_disp_type)
    {
#ifdef NO_RELAX_UI
#else
    case view_relax_animation:
#endif
#ifdef NO_METRONOME_UI
#else
    case view_metronome_state:
#endif
    // case view_sports_result_0:
    // case view_sports_result_1:
    case view_others_camera:
    case view_others_camera_static:
    case view_others_camera_shake:
#ifdef NO_STOPWATCH_UI
#else
    case view_others_stopwatch:
#endif
    case view_others_device_info:
    case view_others_device_info_detail:
#if defined(NO_APP_URL_UI)
#else
    case view_others_app_url:
#endif
    case view_others_power_off:
        return false;
    default:
        if (sports_mode_get_state() == sports_mode_state_idle)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
}
/*********************************************************************************************
 * @brief 查询当前界面优先级
 * @warning
 ********************************************************************************************/
disp_type_priority_t display_get_present_type_priority(void)
{
    disp_type_t current_ui = display_get_present_type();
    if (current_ui == view_empty) //空闲
    {
        return DISP_TYPE_PRIORITY_STANDBY;
    }
    switch (current_ui)
    {
#ifdef NO_STOPWATCH_UI
#else
    case view_others_stopwatch:
#endif
    case view_power_off_animation:
    case view_power_on_animation:
#ifdef NO_METRONOME_UI
#else
    case view_metronome_state:
#endif
#ifdef NO_RELAX_UI
#else
    case view_relax_animation:
    case view_relax_tips:
#endif
        return DISP_TYPE_PRIORITY_SYSTEM;
    case view_prompt_alarm:
        return DISP_TYPE_PRIORITY_ALARM;
    case view_heart_rate_test:
#ifdef AXILLARY_TEMPERATURE
    case view_axillary_test:
#endif
#if defined(USE_CT1711)
    case view_temperature_detail:
#endif
        return DISP_TYPE_PRIORITY_APP_MEASURE;
    case view_heart_rate_result:
        return DISP_TYPE_PRIORITY_ALERT;
    case view_others_camera_static:
    case view_others_camera_shake:
        return DISP_TYPE_PRIORITY_APP_MEASURE;
    case view_prompt_message:
        return DISP_TYPE_PRIORITY_ALARM;
    }
    if (current_ui >= view_prompt_start && current_ui < view_prompt_priority_alert_end) //提醒类界面
    {
        return DISP_TYPE_PRIORITY_ALERT;
    }
    if (current_ui >= view_sports_state_begin && current_ui < view_sports_state_end) //提醒类界面
    {
        return DISP_TYPE_PRIORITY_SYSTEM;
    }
    return DISP_TYPE_PRIORITY_NORMAL;
}
